/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bff.spi.builtin;

import com.fasterxml.jackson.databind.JsonSerializer;
import com.inspur.edp.bff.api.exception.BffFrameworkException;
import com.inspur.edp.bff.spi.BffEntitySerConvertor;
import com.inspur.edp.cef.entity.entity.FieldType;
import com.inspur.edp.cef.spi.entity.PropertyDefaultValue;
import com.inspur.edp.cef.spi.entity.info.EnumValueInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.AssocationPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.BasePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.ComplexUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.DataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.EnumPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.ObjectType;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.SimpleAssoUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.SimpleEnumUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.SimpleUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefModelResInfoImpl;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefValueObjModelResInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefValueObjResInfo;
import com.inspur.edp.udt.api.Manager.IUdtManager;
import com.inspur.edp.udt.api.UdtManagerUtils;

import java.lang.reflect.InvocationTargetException;

public abstract class BffEntityResInfoImpl extends CefEntityResInfoImpl {
    private BffEntitySerConvertor bffEntitySerConvertor;

    public BffEntityResInfoImpl(String entityCode, String displayValueKey, CefModelResInfoImpl modelResInfo, String entityId) {
        super(entityCode, displayValueKey, modelResInfo, entityId);
    }

    @Override
    public JsonSerializer getEntitySerConvertor() {
        if (bffEntitySerConvertor == null) {
            bffEntitySerConvertor = new BffEntitySerConvertor(getEntityTypeInfo().getEntityCode(), isRoot(), getConfigId(), this);
        }
        return bffEntitySerConvertor;
    }

    protected DataTypePropertyInfo addStringPropertyInfo(String propertyName, boolean required, boolean enableRtrim, int length) {
        return addStringPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required, enableRtrim, length, null, false, false, propertyName);
    }

    protected DataTypePropertyInfo addStringPropertyInfo(String propertyName, String displayValueKey, boolean required, boolean enableRtrim, int length,
                                                         PropertyDefaultValue defaultValue, boolean defaultNull, boolean isMulti, String beLabelId) {
        return addBffPropertyInfo(propertyName, displayValueKey, required, enableRtrim, length, 0,
                com.inspur.edp.cef.entity.entity.FieldType.String, ObjectType.Normal, null, defaultValue, isMulti, false, beLabelId, false);
    }

    private BffPropertyInfo addBffPropertyInfo(String propertyName, String displayValueKey, boolean required, boolean enableRtrim, int length, int precision, FieldType fieldType, ObjectType objectType, BasePropertyInfo objectInfo, PropertyDefaultValue defaultValue, boolean isMulti, boolean bigNumber, String beLabelId, boolean enableStdTimeFormat) {
        BffPropertyInfo bffPropertyInfo = new BffPropertyInfo(propertyName, displayValueKey, required, enableRtrim, length, precision, fieldType, objectType, objectInfo, defaultValue, isMulti, bigNumber, beLabelId, enableStdTimeFormat);
        addPropertyInfo(bffPropertyInfo);
        return bffPropertyInfo;
    }

    protected DataTypePropertyInfo addTextPropertyInfo(String propertyName, boolean required, boolean enableRtrim) {
        return addTextPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required,
                enableRtrim, null, false, false, propertyName);
    }

    protected DataTypePropertyInfo addTextPropertyInfo(String propertyName, String displayValueKey, boolean requried, boolean enableRtrim, PropertyDefaultValue defaultValue, boolean isDefaultNull,
                                                       boolean isMulti, String beLabelId) {
        return addBffPropertyInfo(propertyName, displayValueKey, requried, enableRtrim, 0, 0,
                FieldType.Text, ObjectType.Normal, null, defaultValue, isMulti, false, beLabelId, false);
    }

    protected DataTypePropertyInfo addDatePropertyInfo(String propertyName, boolean required) {
        return addDatePropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required, null, false, propertyName);
    }

    protected DataTypePropertyInfo addDatePropertyInfo(String propertyName, String displayValueKey, boolean required, PropertyDefaultValue defaultValue
            , boolean defaultNull, String beLabelID) {
        return addBffPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
                FieldType.Date, ObjectType.Normal, null, defaultValue, false, false, beLabelID, false);
    }

    protected DataTypePropertyInfo addDateTimePropertyInfo(String propertyName, boolean required, boolean enableStdTime) {
        return addDateTimePropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required, null, false, propertyName, enableStdTime);
    }

    protected DataTypePropertyInfo addDateTimePropertyInfo(String propertyName, String displayValueKey, boolean required, PropertyDefaultValue defaultValue,
                                                           boolean defaultNull, String beLabelID, boolean enableStdTime) {
        return addBffPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
                FieldType.DateTime, ObjectType.Normal, null, defaultValue, false, false, beLabelID, enableStdTime);
    }

    protected DataTypePropertyInfo addIntPropertyInfo(String propertyName, boolean required) {
        return addIntPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required, null, false, propertyName);
    }

    protected DataTypePropertyInfo addIntPropertyInfo(String propertyName, String displayValueKey, boolean required, PropertyDefaultValue defaultValue,
                                                      boolean defaultNull, String beLabelID) {
        return addBffPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
                FieldType.Integer, ObjectType.Normal, null, defaultValue, false, false, beLabelID, false);
    }

    protected DataTypePropertyInfo addDecimalPropertyInfo(String propertyName, boolean requried, int length, int pricision) {
        return addDecimalPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                requried, length, pricision, null, false, propertyName, false);
    }

    protected DataTypePropertyInfo addDecimalPropertyInfo(String propertyName, String propertyDispalyKey, boolean requried, int length, int pricision,
                                                          PropertyDefaultValue defaultValue, boolean defaultNull, String beLabelID, boolean isBigNumber) {
        return addBffPropertyInfo(propertyName, propertyDispalyKey, requried, false, 0, 0,
                FieldType.Decimal, ObjectType.Normal, null, defaultValue, false, isBigNumber, beLabelID, false);
    }

    protected DataTypePropertyInfo addBooleanPropertyInfo(String propertyName, boolean requried) {
        return addBooleanPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName), requried, null, false, propertyName);
    }

    protected DataTypePropertyInfo addBooleanPropertyInfo(String propertyName, String propertyDisplayValue, boolean required, PropertyDefaultValue defaultValue,
                                                          boolean defaultNull, String beLabeID) {
        return addBffPropertyInfo(propertyName, propertyDisplayValue, required, false, 0, 0,
                FieldType.Boolean, ObjectType.Normal, null, defaultValue, false, false, beLabeID, false);
    }

    protected DataTypePropertyInfo addBytesPropertyInfo(String propertyName, boolean required) {
        return addBytesPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName), required, null, false, propertyName);
    }

    protected DataTypePropertyInfo addBytesPropertyInfo(String propertyName, String displayValueKey, boolean required, PropertyDefaultValue defaultValue,
                                                        boolean defaultNull, String beLabeID) {
        return addBffPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
                FieldType.Binary, ObjectType.Normal, null, defaultValue, false, false, beLabeID, false);
    }

    protected final DataTypePropertyInfo addAssoUdtPropertyInfo(String propertyName, boolean requried,
                                                                boolean enableRtrim, SimpleAssoUdtPropertyInfo associationInfo) {
        return addAssoUdtPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                requried, enableRtrim, 36, false, associationInfo, propertyName);
    }

    protected final DataTypePropertyInfo addAssoUdtPropertyInfo(String propertyName, boolean requried,
                                                                boolean enableRtrim, SimpleAssoUdtPropertyInfo associationInfo, boolean enableStdTimeFormat) {
        return addAssoUdtPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                requried, enableRtrim, 36, false, associationInfo, propertyName, enableStdTimeFormat);
    }

    protected String getFieldPropertyDisplayValue(String propertyName) {
        return this.getDisplayPrefix() + "." + propertyName + "." + "Name";
    }

    protected final DataTypePropertyInfo addAssoUdtPropertyInfo(String propertyName,
                                                                String propertyDisplayKey, boolean required, boolean enableRtrim, int length,
                                                                boolean isDefaultNull, SimpleAssoUdtPropertyInfo associationInfo, String beLabelID) {
        return addBffPropertyInfo(propertyName, propertyDisplayKey, required, enableRtrim, length, 0, FieldType.Udt, ObjectType.UDT, associationInfo, null, false, false, beLabelID, false);
    }

    protected final DataTypePropertyInfo addAssoUdtPropertyInfo(String propertyName,
                                                                String propertyDisplayKey, boolean required, boolean enableRtrim, int length,
                                                                boolean isDefaultNull, SimpleAssoUdtPropertyInfo associationInfo, String beLabelID, boolean enableStdTimeFormat) {
        return addBffPropertyInfo(propertyName, propertyDisplayKey, required, enableRtrim, length, 0, FieldType.Udt, ObjectType.UDT, associationInfo, null, false, false, beLabelID, enableStdTimeFormat);
    }

    protected final DataTypePropertyInfo addComplexUdtPropertyInfo(String propertyName,
                                                                   ComplexUdtPropertyInfo udtPropertyInfo) {
        return addComplexUdtPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName), udtPropertyInfo, propertyName);
    }

    protected final DataTypePropertyInfo addComplexUdtPropertyInfo(String propertyName, String propertyDisplayValueKey,
                                                                   ComplexUdtPropertyInfo udtPropertyInfo, String beLabelID) {
        return addBffPropertyInfo(propertyName, propertyDisplayValueKey, false, false, 0, 0,
                FieldType.Udt, ObjectType.UDT, udtPropertyInfo, null, false, false, beLabelID, udtPropertyInfo.getEnableStdTimeFormat());
    }

    protected final DataTypePropertyInfo addAssociationProperyInfo(String propertyName, boolean required,
                                                                   boolean enableRtrim,
                                                                   AssocationPropertyInfo associationInfo) {
        return addAssociationProperyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required, enableRtrim, 36, false, associationInfo,
                propertyName);
    }

    protected final DataTypePropertyInfo addAssociationProperyInfo(String propertyName, boolean required,
                                                                   boolean enableRtrim,
                                                                   AssocationPropertyInfo associationInfo, boolean enableStdTimeFormat) {
        return addAssociationProperyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
                required, enableRtrim, 36, false, associationInfo,
                propertyName, enableStdTimeFormat);
    }

    protected final DataTypePropertyInfo addAssociationProperyInfo(String propertyName,
                                                                   String propertyDisplayKey, boolean required, boolean enableRtrim, int length,
                                                                   boolean isDefaultNull, AssocationPropertyInfo associationInfo, String beLabelID) {
        return addBffPropertyInfo(propertyName, propertyDisplayKey, required, enableRtrim, length, 0, FieldType.String, ObjectType.Association, associationInfo, null, false, false, beLabelID, false);
    }

    protected final DataTypePropertyInfo addAssociationProperyInfo(String propertyName,
                                                                   String propertyDisplayKey, boolean required, boolean enableRtrim, int length,
                                                                   boolean isDefaultNull, AssocationPropertyInfo associationInfo, String beLabelID, boolean enableStdTimeFormat) {
        return addBffPropertyInfo(propertyName, propertyDisplayKey, required, enableRtrim, length, 0, FieldType.String, ObjectType.Association, associationInfo, null, false, false, beLabelID, enableStdTimeFormat);
    }

    protected final DataTypePropertyInfo addSimpleUdtPropertyInfo(String propertyName, boolean requried, boolean enableRtrim, String udtConfigId) {
        return addSimpleUdtPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName), requried, enableRtrim, false, udtConfigId, propertyName, false, false);
    }

    protected final DataTypePropertyInfo addSimpleUdtPropertyInfo(String propertyName, boolean requried, boolean enableRtrim, String udtConfigId, boolean enableStdTimeFormat) {
        return addSimpleUdtPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName), requried, enableRtrim, false, udtConfigId, propertyName, enableStdTimeFormat, false);
    }

    protected final DataTypePropertyInfo addSimpleUdtPropertyInfo(String propertyName, String propertyDisplayKey, boolean requried, boolean enableRtrim, boolean isMulti, String udtConfigId, String beLabelID, boolean enableStdTimeFormat, boolean isBigNumber) {
        IUdtManager udtManager = (IUdtManager) UdtManagerUtils.getUdtFactory()
                .createUdtManager(udtConfigId);
        try {
            CefValueObjModelResInfo valueObjModelResInfo = (CefValueObjModelResInfo) udtManager
                    .getClass().getMethod("getUdtModelInfo").invoke(udtManager);
            CefValueObjResInfo valueObjResInfo = (CefValueObjResInfo) valueObjModelResInfo
                    .getCustomResource(valueObjModelResInfo.getRootNodeCode());
            DataTypePropertyInfo udtPropInfo = valueObjResInfo.getEntityTypeInfo()
                    .getPropertyInfo(valueObjResInfo.getEntityCode());

            if (udtPropInfo.getObjectInfo() instanceof EnumPropertyInfo) {
                SimpleEnumUdtPropertyInfo simpleEnumUdtPropertyInfo = new SimpleEnumUdtPropertyInfo(
                        udtConfigId, false);
                EnumPropertyInfo enumPropertyInfo = new EnumPropertyInfo();
                for (EnumValueInfo enumValueInfo : ((EnumPropertyInfo) udtPropInfo.getObjectInfo())
                        .getEnumValueInfos()) {
                    enumPropertyInfo.addEnumValueInfo(
                            propertyDisplayKey.substring(0, propertyDisplayKey.lastIndexOf(".")),
                            enumValueInfo.getEnumCode(), enumValueInfo.getDefaultName(),
                            enumValueInfo.getStringIndex(), enumValueInfo.getIndex());
                }
                simpleEnumUdtPropertyInfo.setEnumInfo(enumPropertyInfo);
                return addBffPropertyInfo(propertyName, propertyDisplayKey, requried, enableRtrim,
                        udtPropInfo.getLength(), udtPropInfo.getPrecision(), FieldType.Udt, ObjectType.UDT,
                        simpleEnumUdtPropertyInfo, null, isMulti, isBigNumber, beLabelID,
                        enableStdTimeFormat);
            } else {
                SimpleUdtPropertyInfo simpleUdtPropertyInfo = new SimpleUdtPropertyInfo(udtConfigId,
                        false);
                return addBffPropertyInfo(propertyName, propertyDisplayKey, requried, enableRtrim,
                        udtPropInfo.getLength(), udtPropInfo.getPrecision(), FieldType.Udt, ObjectType.UDT,
                        simpleUdtPropertyInfo, null, isMulti, isBigNumber, beLabelID, enableStdTimeFormat);
            }

        } catch (IllegalAccessException var10) {
            throw new BffFrameworkException();
        } catch (InvocationTargetException var11) {
            throw new BffFrameworkException();
        } catch (NoSuchMethodException var12) {
            throw new BffFrameworkException();
        }
    }
}
